package cc.rengu.igas.share.core.service.channel.upqc;

import cc.rengu.igas.channel.upqc.facade.base.Header;
import cc.rengu.igas.channel.upqc.facade.bean.CouponInfoBean;
import cc.rengu.igas.channel.upqc.facade.bean.PayerInfo;
import cc.rengu.igas.channel.upqc.facade.request.B2CTranStateQueryRequest;
import cc.rengu.igas.channel.upqc.facade.response.B2CTranStateQueryResponse;
import cc.rengu.igas.channel.upqc.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.enums.FeeTypeEnum;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.AmountUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * UPQC-收款查询（主扫）
 * Created by lzl on 2021/4/23 11:08
 */
public class B2cTransStateQueryService extends ChannelBaseService {
    @Override
    public Object callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Header upqcHeader = new Header();
        upqcHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
        upqcHeader.setChanlId(channelCallCfg.getMsgSrcId());
        upqcHeader.setSrcSysId(AppParamConstant.SYS_ID);
        upqcHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        upqcHeader.setVersion(ShareParamConstant.DUBBO_VSERSION);
        upqcHeader.setTxnNum(channelCallCfg.getCallChannelTxn());
        upqcHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        upqcHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        upqcHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        B2CTranStateQueryRequest b2cTranStateQuery = new B2CTranStateQueryRequest();
        b2cTranStateQuery.setHeader(upqcHeader);
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(upqcHeader.getInstId(), orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
            return null;
        }
        b2cTranStateQuery.setCupsInstCode(mchntInfo.getCupsInstId());
        Predicate<PayOrderInfo> channelFilter = p -> channelCallCfg.getCallChannelId().equals(p.getMsgDstId());
        List<PayOrderInfo> payOrderInfoList = orderInfo.getPayOrderInfoList().stream().filter(channelFilter).collect(Collectors.toList());
        /*设置查询请求报文*/
        b2cTranStateQuery.setOrderId(payOrderInfoList.get(0).getSysSeqNum());
        b2cTranStateQuery.setOrderTime(payOrderInfoList.get(0).getTxnDate() + payOrderInfoList.get(0).getTxnTime());
        rglog.debug("UPQC 收款查询（主扫）请求:<{}>", JSON.toJSONString(b2cTranStateQuery));

        return b2cTranStateQuery;
    }

    @Override
    public PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, Object request) throws Exception {
        //此交易不登记支付订单
        return null;
    }

    @Override
    public Object callProc(ChannelCallCfg channelCallCfg, Object request) throws Exception {
        B2CTranStateQueryRequest b2cTranStateQuery = (B2CTranStateQueryRequest) request;
        /* Step1：调用接口，获取结果 */
        Result<B2CTranStateQueryResponse> callResult;
        DubboService dubboService = new DubboServiceImpl();
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            /* Step1.1：异步调用 */
            int iReturnCode;
            int callTimes = 0 == channelCallCfg.getSyncQueryRepeatNum() ? 1 : channelCallCfg.getSyncQueryRepeatNum();
            int gatTime = channelCallCfg.getSyncQueryRepeatTime();
            int gatType = StringUtil.isEmptyOrNull(channelCallCfg.getSyncQueryGapType()) ? 0 : Integer.parseInt(channelCallCfg.getSyncQueryGapType());
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.1：异步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_SERVICE_INNER_PATH);
                iReturnCode = dubboService.asynCallDubboInnerMethod(clasz, ShareServiceConstant.UPQC_B2C_TRANS_STATE_QUERY_METHOD, b2cTranStateQuery, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.2：异步远程调用 */
                iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.UPQC_SERVICE, ShareServiceConstant.UPQC_B2C_TRANS_STATE_QUERY_METHOD, b2cTranStateQuery, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            if (0 == iReturnCode) {
                return new BizResponse<>(OltpRpcdEnum.TRANS_SUCCESS.getRespCode(), OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                return new BizResponse<>(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
        } else {
            /* Step1.2：同步调用 */
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.1：同步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_SERVICE_INNER_PATH);
                callResult = (Result<B2CTranStateQueryResponse>) dubboService.callDubboInnerMethod(clasz, ShareServiceConstant.UPQC_B2C_TRANS_STATE_QUERY_METHOD, b2cTranStateQuery);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.2：同步远程调用 */
                callResult = (Result<B2CTranStateQueryResponse>) dubboService.callDubboService(ShareServiceConstant.UPQC_SERVICE, ShareServiceConstant.UPQC_B2C_TRANS_STATE_QUERY_METHOD, b2cTranStateQuery);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
        }
        return callResult;
    }

    @Override
    public Object querySyncCallResult(PayOrderInfo payOrderInfo, Object request) {
        return null;
    }

    @Override
    public OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) throws Exception {
        OrderInfo updateOrderInfo = new OrderInfo();
        Result<B2CTranStateQueryResponse> callResult = (Result<B2CTranStateQueryResponse>) response;
        Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item -> item.getDstCallIndex().equals(payOrderIndex)).findFirst();
        if (payOrderInfoOpt.isPresent() && null != callResult && null != callResult.getResult()) {
            UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
            List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();
            PayOrderInfo payOrderInfo = payOrderInfoOpt.get();
            B2CTranStateQueryResponse b2CTranStateQueryResponse = callResult.getResult();
            switch (transStatusEnum) {
                case TRANS_SUCC:
                    if (OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(b2CTranStateQueryResponse.getOrigRespCode()) ||
                            "00".equals(b2CTranStateQueryResponse.getOrigRespCode())) {
                        /* 判断原订单表中的订单金额是否为空或0.00,若是则对三个订单表中的订单金额进行赋值 */
                        if (StringUtil.isEmptyOrNull(userOrderInfo.getOrderAmt()) || AmountUtil.compare(userOrderInfo.getOrderAmt(), "0.00") == 0) {
                            if (StringUtil.isEmptyOrNull(b2CTranStateQueryResponse.getOrigTxnAmt())) {
                                userOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrderAmt());
                                userOrderInfo.setNeedPayAmt(b2CTranStateQueryResponse.getOrderAmt());
                            } else {
                                userOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                                userOrderInfo.setNeedPayAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                            }
                        }
                        if (StringUtil.isEmptyOrNull(payOrderInfo.getOrderAmt()) || AmountUtil.compare(payOrderInfo.getOrderAmt(), "0.00") == 0) {
                            if (StringUtil.isEmptyOrNull(b2CTranStateQueryResponse.getOrigTxnAmt())) {
                                payOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrderAmt());
                            } else {
                                payOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                            }
                        }
                        /* 更新当前用户订单信息 */
                        payOrderInfo.setRealPayAmt(b2CTranStateQueryResponse.getOrderAmt());
                        //银联的营销不影响结算金额，只做记录
                        if (b2CTranStateQueryResponse.getCouponInfoList() != null && !b2CTranStateQueryResponse.getCouponInfoList().isEmpty()) {
                            //有优惠
                            String mchntTotalDistAmt = "0.00";
                            for (CouponInfoBean couponInfoBean : b2CTranStateQueryResponse.getCouponInfoList()) {
                                if ("00010000".equals(couponInfoBean.getSpnsrId())) {
                                    rglog.info("用户支付享受了银联的营销活动，减免了:{}元", couponInfoBean.getOffstAmt());
                                    payOrderInfo.setChannelDiscountAmt(couponInfoBean.getOffstAmt());
                                } else {
                                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                                        if (mchntOrderInfo.getMchntNo().equals(couponInfoBean.getSpnsrId())) {
                                            rglog.info("用户支付享受了商户<{}>的营销活动，减免了:{}元", mchntOrderInfo.getMchntNo(), couponInfoBean.getOffstAmt());
                                            if (StringUtil.isEmptyOrNull(mchntOrderInfo.getOrderAmt()) || AmountUtil.compare(mchntOrderInfo.getOrderAmt(), "0.00") == 0) {
                                                if (StringUtil.isEmptyOrNull(b2CTranStateQueryResponse.getOrigTxnAmt())) {
                                                    mchntOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrderAmt());
                                                    mchntOrderInfo.setRealSettleAmt(b2CTranStateQueryResponse.getOrderAmt());
                                                } else {
                                                    mchntOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                                                    mchntOrderInfo.setRealSettleAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                                                }
                                            }
                                            mchntOrderInfo.setCustomerMarketAmt(couponInfoBean.getOffstAmt());
                                            mchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getCustomerMarketAmt()));
                                            mchntTotalDistAmt = AmountUtil.addition(mchntTotalDistAmt, couponInfoBean.getOffstAmt());
                                        }
                                    }
                                }
                            }
                            String userPrePayDistAmt = StringUtil.isEmptyOrNull(userOrderInfo.getRealDiscountAmt()) ? "0.00" : userOrderInfo.getRealDiscountAmt();
                            String channelTotalDistAmt = AmountUtil.addition(payOrderInfo.getChannelDiscountAmt(), mchntTotalDistAmt);
                            userOrderInfo.setRealDiscountAmt(AmountUtil.addition(userPrePayDistAmt, channelTotalDistAmt));
                            userOrderInfo.setRealPayAmt(AmountUtil.subtraction(userOrderInfo.getNeedPayAmt(), channelTotalDistAmt));
                        }
                        String orderAmt = !StringUtil.isEmptyOrNull(b2CTranStateQueryResponse.getOrigTxnAmt()) ? b2CTranStateQueryResponse.getOrigTxnAmt() : b2CTranStateQueryResponse.getOrderAmt();
                        userOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrderAmt());
                        userOrderInfo.setRealPayAmt(orderAmt);
                        userOrderInfo.setNeedPayAmt(orderAmt);
                        userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                        userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        /* 更新当前商户订单信息*/
                        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                            if (StringUtil.isEmptyOrNull(mchntOrderInfo.getOrderAmt()) ||
                                    AmountUtil.compare(mchntOrderInfo.getOrderAmt(), "0.00") == 0) {
                                mchntOrderInfo.setOrderAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                                mchntOrderInfo.setRealSettleAmt(b2CTranStateQueryResponse.getOrigTxnAmt());
                            }
                            mchntOrderInfo.setRealSettleAmt(orderAmt);
                            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                            mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        }
                        String feeType = FeeTypeEnum.UPQR_CR.getFeeType();
                        if ("01".equals(b2CTranStateQueryResponse.getPayerInfo().getCardAttr())) {
                            feeType = FeeTypeEnum.UPQR_DR.getFeeType();
                        }
                        /* 若商户有计算手续费，则重新计算商户手续费 */
                        MchntService mchntService = new MchntServiceImpl();
                        mchntService.calcMchntFee(mchntOrderInfoList, feeType);
                        /* 更新支付订单信息 */
                        PayerInfo payerInfo = b2CTranStateQueryResponse.getPayerInfo();
                        payOrderInfo.setPayerAcctType(AcctTypeEnum.ALL.getAcctType());
                        SysParamService sysParamService = new SysParamServiceImpl();
                        SysParam sysParam = sysParamService.getSysParamInfo(userOrderInfo.getInstId(), ShareParamConstant.SHARE_SYS_PARAM, ShareParamConstant.CORPORATION_ORG_CODE);
                        if (null != sysParam && null != payerInfo) {
                            List<String> corporationorgList = Arrays.asList(sysParam.getParamValue().split(","));
                            if (corporationorgList.contains(payerInfo.getIssCode())) {
                                payOrderInfo.setPayerAcctType("01".equals(payerInfo.getCardAttr()) ? AcctTypeEnum.BANK_DEBIT.getAcctType() : AcctTypeEnum.BANK_CREDIT.getAcctType());
                            } else {
                                payOrderInfo.setPayerAcctType("01".equals(payerInfo.getCardAttr()) ? AcctTypeEnum.OTHER_DEBIT.getAcctType() : AcctTypeEnum.OTHER_CREDIT.getAcctType());
                            }
                        }
                        payOrderInfo.setOrderAmt(orderAmt);
                        payOrderInfo.setRealPayAmt(orderAmt);
                        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                        payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                        payOrderInfo.setSettleDate(b2CTranStateQueryResponse.getSettleDate());
                        payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        updateOrderInfo.setUserOrderInfo(userOrderInfo);
                        updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    } else if ("04".equals(b2CTranStateQueryResponse.getOrigRespCode()) ||
                            "06".equals(b2CTranStateQueryResponse.getOrigRespCode()) ||
                            "35".equals(b2CTranStateQueryResponse.getOrigRespCode())) {
                        /* 处理中交易，支付中状态，返回处理中判断订单有效时间是否超过有效时间，如果超过有效时间，把定单关闭*/
                        if (DateUtil.compareTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"), userOrderInfo.getOrderExpiryTime(), "yyyyMMddHHmmss") > 0) {
                            userOrderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
                            userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                            userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                                mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                                mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                            }
                            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        }
                    } else {
                        /* 更新当前用户订单信息 */
                        userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        /* 更新当前商户订单信息 */
                        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        }
                        /* 更新当前支付订单信息 */
                        payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        updateOrderInfo.setUserOrderInfo(userOrderInfo);
                        updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    }
                    break;
                case TRANS_TIMEOUT:
                    payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                    break;
                case SYSTEM_REJECT:
                    /* 更新当前用户订单信息 */
                    userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                    userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    /* 更新当前商户订单信息 */
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    }
                    /* 更新当前支付订单信息 */
                    payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    updateOrderInfo.setUserOrderInfo(userOrderInfo);
                    updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    break;
                default:
                    break;
            }
            List<PayOrderInfo> payOrderInfoList = new ArrayList<>();
            payOrderInfoList.add(payOrderInfo);
            updateOrderInfo.setPayOrderInfoList(payOrderInfoList);
        }
        return updateOrderInfo;
    }
}
